// Copyright (C) joyinter
// All rights reserved.
// 
// Author : Jiang Li
// Date   : 2004-7-7

#include "stdafx.h"
#include ".\combobox.h"

// class CJoyComboItem

//##ModelId=44CF17B900C0
CJoyComboItem::CJoyComboItem()
{
}

//##ModelId=44CF17B900C1
CJoyComboItem::~CJoyComboItem()
{
}

//##ModelId=44CF17B900CB
CJoyComboBox* CJoyComboItem::GetComboBox()
{
    return ((CJoyComboList*)m_listView)->m_comboBox;
}

//##ModelId=44CF17B900AC
void CJoyComboItem::CM_MouseLeave()
{
    __super::CM_MouseLeave();
}

//##ModelId=44CF17B900AE
void CJoyComboItem::CM_MouseHover()
{
    __super::CM_MouseHover();
    m_listView->SelItem(this);
}

//##ModelId=44CF17B900B0
void CJoyComboItem::CM_Mouse(MouseMessage msg, const CPoint&)
{
    if(msg == MM_LeftUp)
    {
        GetComboBox()->SelItem(this);
    }
}

//##ModelId=44CF17B900BD
void CJoyComboItem::CM_Draw(Graphics& )
{
}

// class CJoyComboList

IMPLEMENT_DYNAMIC(CJoyComboList, CJoyListView)

//##ModelId=44CF17B900FC
CJoyComboList::CJoyComboList(void)
{
    m_name = "combo_list";
    m_skinArea = true;
}

//##ModelId=44CF17B900FE
CJoyComboList::~CJoyComboList(void)
{
}

//##ModelId=44CF17B900E3
CJoyComboList* CJoyComboList::m_hookList = NULL;
//##ModelId=44CF17B900EA
HHOOK CJoyComboList::m_mouseHook = NULL;

//##ModelId=44CF17B900EB
LRESULT CALLBACK CJoyComboList::MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    LRESULT r = CallNextHookEx(m_mouseHook, nCode, wParam, lParam);
    if(nCode == HC_ACTION)
    {
        MOUSEHOOKSTRUCT* hookInfo = (MOUSEHOOKSTRUCT*)lParam;
        CRect wArea;
        m_hookList->GetWindowRect(&wArea);
        if(!wArea.PtInRect(hookInfo->pt))
        {
            r = 1;

            if(
                (wParam == WM_LBUTTONDOWN) |
                (wParam == WM_LBUTTONUP) |
                (wParam == WM_LBUTTONDBLCLK) |
                (wParam == WM_RBUTTONDOWN) |
                (wParam == WM_RBUTTONUP) |
                (wParam == WM_RBUTTONDBLCLK) |
                (wParam == WM_NCLBUTTONDOWN) |
                (wParam == WM_NCLBUTTONUP) |
                (wParam == WM_NCLBUTTONDBLCLK) |
                (wParam == WM_NCRBUTTONDOWN) |
                (wParam == WM_NCRBUTTONUP) |
                (wParam == WM_NCRBUTTONDBLCLK)
            )
            {
                m_hookList->SetVisible(false);
            }
        }
    }
    return r;
}

BEGIN_MESSAGE_MAP(CJoyComboList, CJoyListView)
    ON_WM_LBUTTONDOWN()
    ON_WM_SHOWWINDOW()
    ON_WM_MOUSEMOVE()
    ON_WM_ACTIVATE()
    ON_WM_SIZE()
    ON_WM_CLOSE()
END_MESSAGE_MAP()

//##ModelId=44CF17B90109
void CJoyComboList::OnLButtonDown(UINT nFlags, CPoint point)
{
    CJoyListView::OnLButtonDown(nFlags, point);

}

//##ModelId=44CF17B90119
void CJoyComboList::OnMouseMove(UINT nFlags, CPoint point)
{
    CJoyListView::OnMouseMove(nFlags, point);

}

//##ModelId=44CF17B9011D
void CJoyComboList::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
    CJoyListView::OnActivate(nState, pWndOther, bMinimized);

    SetVisible(false);
}

//##ModelId=44CF17B90128
void CJoyComboList::OnSize(UINT nType, int cx, int cy)
{
    CJoyListView::OnSize(nType, cx, cy);

    CRect wr;
    GetWindowRect(&wr);
    CPoint orig(0, 0);
    ClientToScreen(&orig);

    orig.x -= wr.left;
    orig.y -= wr.top;
    HRGN h = CreateRectRgn(orig.x, orig.y, orig.x + cx, orig.y + cy);
    SetWindowRgn(h, TRUE);
}

//##ModelId=44CF17B9010D
void CJoyComboList::OnShowWindow(BOOL bShow, UINT nStatus)
{
    CJoyListView::OnShowWindow(bShow, nStatus);

    if(bShow)
    {
        if(m_mouseHook == NULL)
        {
            m_hookList = this;
            m_mouseHook = SetWindowsHookEx(
                WH_MOUSE, MouseProc, NULL, GetCurrentThreadId());
        }
        SetFocus();
    }
    else
    {
        m_hookList = NULL;
        if(m_mouseHook != NULL)
        {
            UnhookWindowsHookEx(m_mouseHook);
            m_mouseHook = NULL;
        }
    }
}

//##ModelId=44CF17B9012D
void CJoyComboList::OnClose()
{
    SetVisible(false);
    // CJoyListView::OnClose();
}

// class CJoyComboBox

IMPLEMENT_DYNAMIC(CJoyComboBox, CJoyWnd)

//##ModelId=44CF17B9017C
CJoyComboBox::CJoyComboBox(void)
{
    m_listHeight= 100;
    m_listMargin= 0;
    m_selMargin = 0;
    m_expMargin = 0;
    m_btnExpand = NULL;
    m_selItem   = NULL;
    m_comboList = NULL;
    
    m_skinArea = true;
}

//##ModelId=44CF17B9017E
CJoyComboBox::~CJoyComboBox(void)
{
}

//##ModelId=44CF17B90167
void CJoyComboBox::BuidlCtrlArea()
{
    // build button area.
    {
        const CRect& btnArea = m_btnExpand->GetArea();
        int w = btnArea.Width();
        int h = btnArea.Height();
        int left = m_area.Width()-m_expMargin-w;
        int top  = (m_area.Height()-h)/2;
        m_btnExpand->SetArea(CRect(left, top, left+w, top+h));
    }
}

//##ModelId=44CF17B90187
void CJoyComboBox::SelItem(CJoyComboItem* item)
{
    m_comboList->SetVisible(false);
    CM_SelItem(item);
}

//##ModelId=44CF17B90189
CJoyComboItem* CJoyComboBox::SelItem(int i)
{
    CJoyComboItem* item = (CJoyComboItem*)m_comboList->SelItem(i);
    SelItem(item);
    return item;
}

//##ModelId=44CF17B9018B
int CJoyComboBox::GetItemIndex(CJoyComboItem* item)
{
    return m_comboList->GetItemIndex(item);
}

//##ModelId=44CF17B90168
CJoyComboList* CJoyComboBox::CreateList()
{
    return new CJoyComboList();
}

BEGIN_MESSAGE_MAP(CJoyComboBox, CJoyWnd)
    ON_WM_CREATE()
    ON_WM_SIZE()
    ON_WM_DESTROY()
END_MESSAGE_MAP()

//##ModelId=44CF17B9016A
void CJoyComboBox::CM_SelItem(CJoyComboItem* item)
{
    m_selItem = item;
    InvalidateCtrl();
}

//##ModelId=44CF17B90179
void CJoyComboBox::CM_LoadSkin(CJoyXmlElement* pSkinElem)
{
    __super::CM_LoadSkin(pSkinElem);

    m_comboList->LoadSkin(pSkinElem->GetElement("combo_list"));

    m_selMargin = pSkinElem->ReadIntD("sel_margin", m_selMargin);
    m_expMargin = pSkinElem->ReadIntD("exp_margin", m_expMargin);
    m_listMargin = pSkinElem->ReadIntD("list_margin", m_listMargin);
    m_listHeight = pSkinElem->ReadIntD("list_height", m_listHeight);

    BuidlCtrlArea();
}

//##ModelId=44CF17B9016D
void CJoyComboBox::CM_Expand(CJoyButton*)
{
    CPoint pt(0, m_area.Height());
    this->ClientToScreen(&pt);

    m_comboList->SetVisible(true);
    m_comboList->SetArea(CRect(pt.x, pt.y+m_listMargin, pt.x+m_area.Width(), pt.y+m_listHeight));
}

//##ModelId=44CF17B9018D
int CJoyComboBox::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CJoyWnd::OnCreate(lpCreateStruct) == -1)
        return -1;

    m_btnExpand = new CJoyButton();
    m_btnExpand->m_name = "btn_expand";
    m_btnExpand->Create(this, CRect(0, 0, 10, 10));
	m_btnExpand->SetClickEvent(this, static_cast<CJoyButton::PClickEvent>(&CJoyComboBox::CM_Expand));

    m_comboList = CreateList();
    m_comboList->m_name = "combo_list";
    m_comboList->m_comboBox = this;
    m_comboList->CreateEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL, WS_POPUP, 0, 0, 10, 10, NULL, 0);
    m_comboList->SetArea(CRect(0, 0, 20, 20));

    return 0;
}

//##ModelId=44CF17B90198
void CJoyComboBox::OnSize(UINT nType, int cx, int cy)
{
    CJoyWnd::OnSize(nType, cx, cy);

    BuidlCtrlArea();
}

//##ModelId=44CF17B9019D
void CJoyComboBox::OnDestroy()
{
    CJoyWnd::OnDestroy();

    if(m_comboList != NULL)
    {
        m_comboList->Destroy();
        delete m_comboList;
        m_comboList = NULL;
    }
}
